// => sort

// Includes

#include "algorithms/sort.h"

#include <stddef.h>

// Functions

/// @func: defaultComparator {PRIVATE}
/// => default comparator, ascending
/// @param: <e1> the first element  [ ElemType ]
/// @param: <e2> the second element [ ElemType ]
/// @return: the compare result, -1 LT, 0 EQ, 1 GT [ int ]
int DefaultComparator(ElemType e1, ElemType e2) {
  ElemType difference = e1 - e2;
  if (difference > 0) {
    return 1;
  } else if (difference < 0) {
    return -1;
  } else {
    return 0;
  }
}

/// @func: BubbleSort
/// >> sort array by bubble sort algorithm
/// @param: <array> the array [ ElemType * ]
/// @param: <start> the start of range [ size_t ]
/// @param: <end> the end of range [ size_t ]
/// @descript: this function will change the original array
void BubbleSort(ElemType *array, size_t start, size_t end) {
  BubbleSortM(array, start, end, DefaultComparator);
}

/// @func: BubbleSortM
/// >> sort array by bubble sort algorithm using specified method
/// @param: <array> the array [ ElemType * ]
/// @param: <start> the start of range [ size_t ]
/// @param: <end> the end of range   [ size_t ]
/// @param: <m> the method [ int (*)(ElemType, ElemType) ]
/// @descript:
///   * this function will change the original array
///   * the method will return -1, 0 and 1 for LT, EQ, GT
void BubbleSortM(ElemType *array, size_t start, size_t end,
                 int (*m)(ElemType, ElemType)) {
  for (size_t i = start; i < end; ++i) {
    for (size_t j = start; j < end - 1 - i; ++j) {
      if (m(array[j], array[j + 1]) > 0) {
        ElemType temp = array[j];
        array[j] = array[j + 1];
        array[j + 1] = temp;
      }
    }
  }
}